import 'dart:convert';
import 'dart:io';

import 'package:logger/logger.dart';

import 'date_time_util.dart';
import 'io_uitl.dart';

// enum Level {
//   verbose,
//   debug,
//   info,
//   warning,
//   error,
//   wtf,
//   nothing,
// }


/// Writes the log output to a file.
class FileOutput extends LogOutput {
  final bool overrideExisting;
  final Encoding encoding;
  final Level level;
  IOSink? _sink;

  File? file;
  String? _currentDate;

  FileOutput({
    this.level = Level.info,
    this.overrideExisting = false,
    this.encoding = utf8,
  });

  Future<void> getDirectoryForLogRecord() async {
    String currentDate = getCurrentDay();
    if (currentDate != _currentDate) {
      final String fileDir = await IoUtil.createDirectory();
      file = File('$fileDir/${currentDate}_${level.name}.log');

      _sink = file!.openWrite(
        mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend,
        encoding: encoding,
      );

      _currentDate = currentDate;
    }
  }

  String getCurrentDay() {
    String currentDate =
    DateTimeUtil.formatDate(DateTime.now(), format: "yyyyMMdd");
    return currentDate;
  }

  // @override
  // void init() {
  //   directoryLogRecord(onCallback: () {});
  // }
  //
  // @override
  // void destroy() async {
  //   await _sink?.flush();
  //   await _sink?.close();
  // }

  void directoryLogRecord({required Function onCallback}) {
    getDirectoryForLogRecord().whenComplete(() {
      onCallback();
    });
  }

  @override
  void output(OutputEvent event) {
    directoryLogRecord(onCallback: () {
      if (_sink != null) {
        if (event.level == level) {
          _sink?.writeln('${event.origin.time} ${event.origin.message}');
          if(event.origin.error != null){
            _sink?.writeln(event.origin.error.toString());
          }
          if(event.origin.stackTrace != null){
            _sink?.writeln(event.origin.stackTrace.toString());
          }
        }
      }
    });
  }
}


class LoggerManager {
  //私有构造函数
  LoggerManager._internal() {
    deleteLogsOfBefore7Day();
    init();
  }

  //保存单例
  static final LoggerManager _singleton = LoggerManager._internal();

  //工厂构造函数
  factory LoggerManager() => _singleton;

  late Logger logger;

  // log初始化设置
  Future<void> init() async {
    logger = Logger(
      filter: DevelopmentFilter(),
      // Use the default LogFilter (-> only log in debug mode)
      // printer: SimplePrinter(
      //   colors: true,
      //   printTime: true,
      // ),
      printer: HybridPrinter(
        PrettyPrinter(
          noBoxingByDefault: false,
          methodCount: 2,
          // number of method calls to be displayed
          errorMethodCount: 8,
          // number of method calls if stacktrace is provided
          lineLength: 120,
          // width of the output
          colors: true,
          // Colorful log messages
          printEmojis: false,
          // Print an emoji for each log message
          printTime: true, // Should each log print contain a timestamp
        ),
        debug: SimplePrinter(),
      ),

      // printer: PrefixPrinter(PrettyPrinter(
      //   noBoxingByDefault: true,
      //   methodCount: 2,
      //   // number of method calls to be displayed
      //   errorMethodCount: 8,
      //   // number of method calls if stacktrace is provided
      //   lineLength: 120,
      //   // width of the output
      //   colors: true,
      //   // Colorful log messages
      //   printEmojis: false,
      //   // Print an emoji for each log message
      //   printTime: true, // Should each log print contain a timestamp
      // )),

      // printer: PrettyPrinter(
      //   noBoxingByDefault: true,
      //   methodCount: 2,
      //   // number of method calls to be displayed
      //   errorMethodCount: 8,
      //   // number of method calls if stacktrace is provided
      //   lineLength: 120,
      //   // width of the output
      //   colors: true,
      //   // Colorful log messages
      //   printEmojis: false,
      //   // Print an emoji for each log message
      //   printTime: true, // Should each log print contain a timestamp
      // ),
      // Use the PrettyPrinter to format and print log
      output: MultiOutput(
        [ConsoleOutput(), FileOutput(level: Level.verbose), FileOutput(level: Level.debug), FileOutput(level: Level.info), FileOutput(level: Level.warning),FileOutput(level: Level.error)],
      ), // Use the default LogOutput (-> send everything to console)
    );
  }

  // Debug
  void debug(String message) {
    logger.d(message);
  }

  // verbose
  void verbose(String message) {
    logger.v(message);
  }

  // info
  void info(String message) {
    logger.i(message);
  }

  // warning
  void warning(String message) {
    logger.w(message);
  }

  // error
  void error(String message) {
    logger.e(message);
  }

  // 每次启动只保留7天内的日志，删除7天前的日志
  Future<void> deleteLogsOfBefore7Day() async {
    final String fileDir = await IoUtil.createDirectory();

    // 获取目录的所有文件
    var dir = Directory(fileDir);
    Stream<FileSystemEntity> files = dir.list();
    await for (FileSystemEntity file in files) {
      // 获取文件的的名称
      List<String> paths = file.path.split(Platform.pathSeparator);
      if (paths.isNotEmpty) {
        String logName = paths.last.split('_').first.replaceAll('.log', '');
        final logDate = DateTimeUtil.getDateTime(logName);
        final currentDate = DateTime.now();
        //比较相差的天数
        final difference = currentDate.difference(logDate).inDays;
        print("deleteLogsOfBefore7Day logDate:$logDate, currentDate:$currentDate, difference:$difference");
        if (difference > 7) {
          var currentFile = File(file.path);
          // 删除文件
          currentFile.delete();
        }
            }
    }
  }

// verbose:
//  LoggerManager().verbose("App started at main.dart");

// debug:
//  LoggerManager().debug("App started at main.dart");

// info:
//  LoggerManager().info("App started at main.dart");

// warning:
//  LoggerManager().warning("App started at main.dart");

// error:
//  LoggerManager().error("App started at main.dart");

// wtf:
//  LoggerManager().wtf("App started at main.dart");

// nothing:
//  LoggerManager().nothing("App started at main.dart");

}